package Game 
{
	import flash.geom.Point;
	/**
	 * ...
	 * @author Vijay Ramani
	 */
	public class Ship extends GameEntity 
	{
		private static const START_ENERGY_VALUE:uint = 50;
		private static const HEALTH_REGEN_RATE:Number = 1.01;
		private static const HEALTH_MAX_VALUE:uint = 100;
		private static const TURN_ANGLE:Number = (3 * Math.PI / 180);
		private static const START_SPEED:Number = 3;
		private static const START_COLLISION_RADIUS:Number = 30;
		private static const ENERGY_CAPTURE_RADIUS:Number = 100;
		private static const BOUNDARY_CLEARANCE:uint = 10;
		
		private var attack:Number = 0;
		private var shield:Number = 0;
		private var speed:Number = START_SPEED;
		private var health:uint = HEALTH_MAX_VALUE;
		private var dir:Point = new Point(1, 0);
		private var vel:Point = new Point(0, 0);
		private var angle:Number = 0;
		
		private var closestEnergy:GameEntity = null;
		private var dirClosestEnergy:Point = new Point();
		private var distClosestEnergy:Number = 0;
		private var collRadius:uint = START_COLLISION_RADIUS;
		
		private var worldBoundExceeded:Point = new Point();
		
		public function Ship() 
		{
			EnergyValue = START_ENERGY_VALUE;
			Init();
			super(GameEntity.TYPE_SHIP);
		}
		public function Init():void
		{
			// Init all the graphics here
			Render();
		}
		
		private function Render():void
		{
			var _rad:uint = 20;
			graphics.lineStyle(1, 0xFFFF00);
			graphics.beginFill(0xFFFF00);
			graphics.moveTo(_rad * Math.cos(0 * Math.PI / 180), _rad * Math.sin(0 * Math.PI / 180));
			graphics.lineTo(_rad * Math.cos(140 * Math.PI / 180), _rad * Math.sin(140 * Math.PI / 180));
			graphics.lineTo(_rad * 0.5 * Math.cos(180 * Math.PI / 180), _rad * 0.5 * Math.sin(180 * Math.PI / 180));
			graphics.lineTo(_rad * Math.cos(220 * Math.PI / 180), _rad * Math.sin(220 * Math.PI / 180));
			graphics.endFill();
			
			graphics.lineStyle(1, 0xFFFFFF);
			graphics.drawCircle(0, 0, collRadius);
			
			//graphics.lineStyle(1, 0xFF0000);
			//graphics.drawCircle(0, 0, ENERGY_CAPTURE_RADIUS);
		}
		
		override final public function Update():void
		{
			super.Update();
			
			HandleEnergyAbsorption();
			
			UpdateShip();
			
			vel.x = dir.x * speed;
			vel.y = dir.y * speed;
			Pos = Pos.add(vel);
			
			worldBoundExceeded.x = 0;
			worldBoundExceeded.y = 0;
			if (Pos.x - collRadius < WorldRef.Bounds.left)
			{
				Pos.x = WorldRef.Bounds.left + collRadius;
				worldBoundExceeded.x = -1;
			}
			else if (Pos.x + collRadius > WorldRef.Bounds.right)
			{
				Pos.x = WorldRef.Bounds.right - collRadius;
				worldBoundExceeded.x = 1;
			}
			
			if (Pos.y - collRadius < WorldRef.Bounds.top)
			{
				Pos.y = WorldRef.Bounds.top + collRadius;
				worldBoundExceeded.y = -1;
			}
			else if (Pos.y + collRadius > WorldRef.Bounds.bottom)
			{
				Pos.y = WorldRef.Bounds.bottom - collRadius;
				worldBoundExceeded.y = 1;
			}
			
		}
		
		private function HandleEnergyAbsorption():void
		{
			closestEnergy = SectorRef.GetClosestEnergy(this);
			if (!closestEnergy)
			{
				dirClosestEnergy.x = 0;
				dirClosestEnergy.y = 0;
				return;
			}
			
			dirClosestEnergy = closestEnergy.Pos.subtract(Pos);
			distClosestEnergy = dirClosestEnergy.length;
			dirClosestEnergy.normalize(1);
			
			if (closestEnergy.Type == GameEntity.TYPE_PELLET && distClosestEnergy <= ENERGY_CAPTURE_RADIUS)
			{
				(closestEnergy as EnergyPellet).Capture(this);
			}
		}
		
		public function UpdateShip():void
		{
			
		}
		
		public final function TurnLeft():void
		{
			Turn( -1);
		}
		public final function TurnRight():void
		{
			Turn( +1);
		}
		
		private final function Turn(_dir:int = 0):void
		{
			angle += _dir * TURN_ANGLE;
			dir.x = Math.cos(angle);
			dir.y = Math.sin(angle);
			
			rotation = angle * 180 / Math.PI;
		}
		
		public function get Attack():uint 
		{
			return attack;
		}
		
		public function set Attack(_value:uint):void 
		{
			attack = _value;
		}
		
		public function get Shield():uint 
		{
			return shield;
		}
		
		public function set Shield(_value:uint):void 
		{
			shield = _value;
		}
		
		public function get Speed():uint 
		{
			return speed;
		}
		
		public function set Speed(_value:uint):void 
		{
			speed = _value;
		}
		
		public function get Health():uint 
		{
			return health;
		}
		
		public function get Direction():Point
		{
			return dir;
		}
		public function get DirClosestEnergy():Point
		{
			return dirClosestEnergy;
		}
		public function get ClosestEnergy():GameEntity
		{
			return closestEnergy;
		}
		public function get WorldBoundsExceeded():Point
		{
			return worldBoundExceeded;
		}
	}

}